package com.agenda.client;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import com.agenda.client.listeners.RecebimentoClienteListener;
import com.agenda.model.Sala;
import com.agenda.model.Usuario;
import com.agenda.model.UsuarioIP;
import com.agenda.util.FileUtil;

public class RequisicaoAoClienteThread implements Runnable {

	public static final int SOLICITACAO_CHAT = 0;
	public static final int MENSAGEM_CHAT = 1;
	public static final int RESPOSTA_SOLICITACAO_CHAT = 2;
	public static final int ABRIR_TELA_CHAT = 3;
	public static final int INICIAR_VIDEO = 4;
	public static final int ENVIAR_ARQUIVO = 5;
	public static final int FECHAR_CHAT = 6;
	public static final int FECHAR_VIDEO = 7;

	public static HashMap<Usuario, Socket> sckClientes = new HashMap<Usuario, Socket>();

	private Socket sck;
	private Usuario usuarioDessaThread;

	public RequisicaoAoClienteThread(Socket sck) {
		super();
		this.sck = sck;
	}

	@Override
	public void run() {
		while (sck != null && !sck.isClosed() && !sck.isInputShutdown()) {
			try {
				InputStream input = sck.getInputStream();

				int requisicao = input.read();
				System.out.println("Requisição que veio do cliente " + sck + " ReqNumero = " + requisicao);

				if (requisicao == SOLICITACAO_CHAT) {
					solicitouChat(input);
				}
				if (requisicao == MENSAGEM_CHAT) {
					recebeuMensagem(input);
				}
				if (requisicao == RESPOSTA_SOLICITACAO_CHAT) {
					respostaSolicitacaoChat(input);
				}
				if (requisicao == ABRIR_TELA_CHAT) {
					abrirTelaChat(input);
				}
				if (requisicao == INICIAR_VIDEO) {
					iniciarVideo(input);
				}
				if (requisicao == ENVIAR_ARQUIVO) {
					receberArquivo(sck);
				}
				if (requisicao == FECHAR_CHAT) {
					fecharTelaChat(input);
				}
				if (requisicao == FECHAR_VIDEO) {
					fecharVideo(input);
				}
			} catch (SocketException e) {
				e.printStackTrace();

				if (usuarioDessaThread != null) {
					sckClientes.remove(usuarioDessaThread);
				}

				break;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private void fecharVideo(InputStream input) throws Exception {
		ObjectInputStream objectInput = new ObjectInputStream(input);

		Sala sala = (Sala) objectInput.readObject();

		ConcurrentHashMap<String, Object> valores = new ConcurrentHashMap<String, Object>();

		valores.put("sala", sala);

		fireEvent(FECHAR_VIDEO, valores);
	}

	private void fecharTelaChat(InputStream input) throws Exception {
		ObjectInputStream objectInput = new ObjectInputStream(input);

		Sala sala = (Sala) objectInput.readObject();

		ConcurrentHashMap<String, Object> valores = new ConcurrentHashMap<String, Object>();

		valores.put("sala", sala);

		fireEvent(FECHAR_CHAT, valores);
	}

	private void receberArquivo(Socket sck) throws Exception {

		ObjectInputStream objectInput = new ObjectInputStream(sck.getInputStream());

		Sala sala = (Sala) objectInput.readObject();
		Usuario usuario = (Usuario) objectInput.readObject();
		String nomeArquivo = (String) objectInput.readObject();

		ConcurrentHashMap<String, Object> valores = new ConcurrentHashMap<String, Object>();

		valores.put("sala", sala);
		valores.put("usuario", usuario);
		valores.put("nomeArquivo", nomeArquivo);

		System.out.println("Arquivo atual " + nomeArquivo);
		BufferedInputStream bufferInput = new BufferedInputStream(sck.getInputStream(), 1024);
		File file = new File(nomeArquivo);
		BufferedOutputStream fileOutputStream = new BufferedOutputStream(new FileOutputStream(file));

		FileUtil.receber(fileOutputStream, bufferInput, sck.getOutputStream());

		fileOutputStream.flush();
		fileOutputStream.close();

		fireEvent(ENVIAR_ARQUIVO, valores);
	}

	private void iniciarVideo(InputStream input) throws Exception {
		ObjectInputStream objectInput = new ObjectInputStream(input);

		Sala sala = (Sala) objectInput.readObject();
		Usuario usuario = (Usuario) objectInput.readObject();

		ConcurrentHashMap<String, Object> valores = new ConcurrentHashMap<String, Object>();

		valores.put("sala", sala);
		valores.put("usuario", usuario);

		fireEvent(INICIAR_VIDEO, valores);
	}

	private void abrirTelaChat(InputStream input) throws Exception {
		ObjectInputStream objectInput = new ObjectInputStream(input);

		Sala sala = (Sala) objectInput.readObject();

		ConcurrentHashMap<String, Object> valores = new ConcurrentHashMap<String, Object>();

		valores.put("sala", sala);

		fireEvent(ABRIR_TELA_CHAT, valores);
	}

	private void respostaSolicitacaoChat(InputStream input) throws Exception {
		System.out.println("Solicitacao resposta 01 ");
		ObjectInputStream objectInput = new ObjectInputStream(input);
		System.out.println("Solicitacao resposta 02 ");
		Sala sala = (Sala) objectInput.readObject();
		System.out.println("Solicitacao resposta 03 ");
		Usuario usuario = (Usuario) objectInput.readObject();
		System.out.println("Solicitacao resposta 04 ");
		Boolean resposta = (Boolean) objectInput.readObject();
		System.out.println("Solicitacao resposta 05 ");

		ConcurrentHashMap<String, Object> valores = new ConcurrentHashMap<String, Object>();

		valores.put("sala", sala);
		valores.put("usuario", usuario);
		valores.put("resposta", resposta);

		usuarioDessaThread = usuario;

		fireEvent(RESPOSTA_SOLICITACAO_CHAT, valores);
	}

	private void recebeuMensagem(InputStream input) throws Exception {

		ObjectInputStream objectInput = new ObjectInputStream(input);

		Sala sala = (Sala) objectInput.readObject();
		Usuario usuario = (Usuario) objectInput.readObject();
		String mensagem = (String) objectInput.readObject();

		ConcurrentHashMap<String, Object> valores = new ConcurrentHashMap<String, Object>();

		valores.put("sala", sala);
		valores.put("usuario", usuario);
		valores.put("mensagem", mensagem);

		fireEvent(MENSAGEM_CHAT, valores);
	}

	private static void fireEvent(int requisicao, ConcurrentHashMap<String, Object> valores) {

		List<RecebimentoClienteListener> recebedores = new ArrayList(ClienteServidor.getINSTANCIA().getRecebedoresListener());

		System.out.println(recebedores);
		for (RecebimentoClienteListener recebimentoListener : recebedores) {
			System.out.println("RECEBEDOR ==++++++++ " + recebimentoListener);
			recebimentoListener.receber(requisicao, valores);
		}
	}

	private void solicitouChat(InputStream input) throws Exception {
		ObjectInputStream objectInput = new ObjectInputStream(input);

		Sala sala = (Sala) objectInput.readObject();
		UsuarioIP usuario = (UsuarioIP) objectInput.readObject();

		ConcurrentHashMap<String, Object> valores = new ConcurrentHashMap<String, Object>();

		valores.put("sala", sala);
		valores.put("usuario", usuario);

		fireEvent(SOLICITACAO_CHAT, valores);
	}
}
